package com.zl.learning.io.zip;

import org.apache.tika.exception.TikaException;
import org.junit.Test;
import org.zeroturnaround.zip.ZipUtil;

import java.io.*;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.FileSystem;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * @author Cay Horstmann
 * @version 1.4 2012-06-01
 */
public class ZipTest {
    public static void main(String[] args) throws IOException {
//      String zipname = args[0];
//        String zipname = "D:\\ztree.zip";
        String zipname = "C:\\data\\data.zip";
        showContents(zipname);
        System.out.println("---------------------------------------------------------------------------------------------");
        showContents2(zipname);
    }

    public static void showContents(String zipname) throws IOException {
        // Here, we use the classic zip API
        try (ZipInputStream zin = new ZipInputStream(new FileInputStream(zipname), Charset.forName("GBK"))) {
            ZipEntry entry;
            while ((entry = zin.getNextEntry()) != null) {
                System.out.println(entry.getName());

//                Scanner in = new Scanner(zin, "gbk");
//                while (in.hasNextLine())
//                    System.out.println("   " + in.nextLine());
                // DO NOT CLOSE in
                zin.closeEntry();
            }
        }
    }

    public static void showContents2(String zipname) throws IOException {
        // Here, we make a Java SE 7 file system
        Map<String, Object> env = new HashMap<>();
        env.put("encoding", "GBK");
        URI uri = URI.create("jar:file:" + Paths.get(zipname).toUri().getPath());
        FileSystem fs = FileSystems.newFileSystem(uri, env);
        Files.walkFileTree(fs.getPath("/"), new SimpleFileVisitor<Path>() {
            public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) throws IOException {
                System.out.println(path);
//                for (String line : Files.readAllLines(path, Charset.forName("gbk")))
//                    System.out.println("   " + line);
                return FileVisitResult.CONTINUE;
            }
        });
    }

    @Test
    public void test1() {
        ZipUtil.pack(new File("data"), new File("data.zip"));
    }

    @Test
    public void test2() throws FileNotFoundException {
//        ZipUtil.unpack(new File("data.zip"), new File("data2"));
        ZipUtil.unpack(new FileInputStream("C:\\data\\data.zip"), new File("data/data2"), Charset.forName("GBK"));
    }

    @Test
    public void test3() {
        CRC32 crc32 = new CRC32();
        crc32.update("55 AA 01 78 0C 00 43 00 2A 14 47 03 00 01 00".replace("\\s", "").getBytes());
        System.out.println(crc32.getValue());
    }

    @Test
    public void test4() throws IOException {
        Path path = Paths.get("C:\\Users\\zhaolei\\Desktop\\新建文件夹\\新建文件夹", "data.zip");
        FileSystem fs = FileSystems.newFileSystem(path, null);
        Files.walkFileTree(fs.getPath("/"), new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
//                fs.
                return super.visitFile(file, attrs);
            }
        });
    }

    @Test
    public void test5() throws IOException, TikaException {
        File resource = new File("C:\\data\\tmp\\人脸2.zip");
        File target = new File("C:\\data\\tmp\\人脸");
//        AutoDetectReader ar = new AutoDetectReader(new FileInputStream(resource));
//        ZipUtil.unpack(resource, target, Charset.forName("GBK"));
        ZipUtil.pack(target, resource);
    }

    @Test
    public void test6() throws IOException {
        Path p = Paths.get("C:\\data\\target");
        Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                System.out.println(file);
                System.out.println(file.getFileName());
//                Files.delete(file);
                return super.visitFile(file, attrs);
            }

            @Override
            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
//                Files.delete(dir);
                return super.postVisitDirectory(dir, exc);
            }
        });
    }

    @Test
    public void test7() {
        unZip("C:\\data\\data.zip", "data");
    }

    public void unZip(String zipFile, String target) {
        byte[] buff = new byte[1024];
        try (ZipInputStream zin = new ZipInputStream(new FileInputStream(zipFile), Charset.forName("GBK"))) {
            ZipEntry entry;
            while ((entry = zin.getNextEntry()) != null) {
                System.out.println(entry.getName());
                File tmp = new File(target + "/" + entry.getName());
                if (entry.isDirectory()) {
                    tmp.mkdirs();
                } else {
                    OutputStream os = new FileOutputStream(tmp);
                    int len;
                    while ((len = zin.read(buff)) != -1) {
                        os.write(buff, 0, len);
                    }
                    os.close();
                }
                zin.closeEntry();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void toZip(String source, String target) {
        File inputFile = new File(source);
        String inputDirPath = inputFile.getAbsolutePath();
        byte[] buffer = new byte[1024];
        Queue<File> files = new LinkedList<>(Arrays.asList(inputFile.listFiles()));
        try (FileOutputStream fileOs = new FileOutputStream(target);
             ZipOutputStream zipOs = new ZipOutputStream(fileOs, Charset.forName("GBK"));) {
            File file;
            while ((file = files.poll()) != null) {
                String filePath = file.getAbsolutePath();
                System.out.println("Zipping " + filePath);
                String entryName = filePath.substring(inputDirPath.length() + 1);
                if (file.isDirectory()) {
                    files.addAll(Arrays.asList(file.listFiles()));
                    ZipEntry ze = new ZipEntry(entryName + "/");
                    zipOs.putNextEntry(ze);
                    zipOs.closeEntry();
                } else {
                    ZipEntry ze = new ZipEntry(entryName);
                    zipOs.putNextEntry(ze);
                    FileInputStream fileIs = new FileInputStream(filePath);
                    int len;
                    while ((len = fileIs.read(buffer)) > 0) {
                        zipOs.write(buffer, 0, len);
                    }
                    fileIs.close();
                    zipOs.closeEntry();
                }

            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void test8() {
        toZip("人脸", "face.zip");
    }
}